package com.starsoft.quant.executor;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import com.starsoft.quant.executor.StrategyRunningStatus.RunningStatus;

@Component
public class ThreadStrategyExecutor{
	
	private static Logger logger = LoggerFactory.getLogger(ThreadStrategyExecutor.class);
	
	@Resource(name="poolTaskExecutor")
	ThreadPoolTaskExecutor poolTaskExecutor;
	
	@Autowired
	StrategyExecutor executor;
	
	Map<Integer, StrategyRunningStatus> runningStatusMap = new HashMap<>();
	
	public String getStatusStr(Integer acountId) {
		StrategyRunningStatus status = runningStatusMap.get(acountId);
		if (status == null) {
			return "无记录";
		} else {
			return status.getStatusStr();
		}
	}
	
	public void backTest(Integer acountId) throws Exception{
		if(checkRuningStatus(acountId)){
			throw new Exception("Strategy is runing now, Pls wait");
		}
		try {
			poolTaskExecutor.execute(new ThreadBackTestJob(acountId));
		} catch(Exception e) {
			runningStatusMap.get(acountId).errorRun();
			throw e;
		}
	}
	
	private synchronized boolean checkRuningStatus(Integer acountId){
		if(runningStatusMap.get(acountId)!=null){
			StrategyRunningStatus status = runningStatusMap.get(acountId);
			if(status.getStatus() == RunningStatus.Pedding || status.getStatus() == RunningStatus.Running){
				return true;
			}
		}
		runningStatusMap.put(acountId, new StrategyRunningStatus(acountId));
		return false;
	}

	class ThreadBackTestJob implements Runnable {
		Integer acountId;

		public ThreadBackTestJob(Integer acountId) {
			this.acountId = acountId;
		}

		@Override
		public void run() {
			StrategyRunningStatus status = runningStatusMap.get(acountId);
			try {
				logger.info("start Test");
				long t1 = System.currentTimeMillis();
				executor.backTest(acountId, status);
				logger.info("End Test time:{}s", (System.currentTimeMillis() - t1) / 1000);
			} catch (Exception e) {
				logger.info("回测失败", e);
			} finally {
				if (status.getStatus() != RunningStatus.Finish){
					status.errorRun();
				}
			}
		}
	}
	
}

